/*
 * Copyright (c) 2018-2028 兰州安众信息科技有限公司 All Rights Reserved.
 * ProjectName: 甘肃九建OA系统
 */

package com.book.manager.oauth2;

import com.book.manager.security.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;

import java.util.Arrays;

@Configuration
@EnableAuthorizationServer
public class MyAuthorizationServerConfigurerAdapter extends AuthorizationServerConfigurerAdapter {

	@Value("${spring.security.oauth2.client.clientId}")
	private String clientId;
	@Value("${spring.security.oauth2.client.clientSecret}")
	private String clientSecret;
	@Value("${spring.security.oauth2.client.authorizedGrantTypes}")
	private String authorizedGrantTypes;
	@Value("${spring.security.oauth2.client.scopes}")
	private String[] scopes;
	@Value("${spring.security.oauth2.client.accessTokenValiditySeconds}")
	private int accessTokenValiditySeconds;
	@Value("${spring.security.oauth2.client.refreshTokenValiditySeconds}")
	private int refreshTokenValiditySeconds;
	@Value("${spring.security.oauth2.client.resourceIds}")
	private String resourceIds;

	@Autowired
	private MyUserDetailsService userDetailsService;

//	@Bean
//	public JwtAccessTokenConverter jwtAccessTokenConverter() {
//		JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
//		/*设置签名*/
//		accessTokenConverter.setSigningKey("smallsnail");
//		return accessTokenConverter;
//	}

	@Autowired
	private AuthenticationManager authenticationManager;

	@Autowired
	private RedisConnectionFactory redisConnection;
//	@Autowired
//	private MyUserDetailsService userDetailsService;
//	@Autowired
//    private DataSource dataSource;


//    public ClientDetailsService clientDetailsService() {
//        return new JdbcClientDetailsService(dataSource);
//    }

	@Bean
	public TokenStore redisTokenStore() {
		return new MyTokenStore(redisConnection);
	}

	@Override
	public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
		//允许表单认证
		oauthServer.allowFormAuthenticationForClients().tokenKeyAccess("isAuthenticated()")
				.checkTokenAccess("permitAll()");
//		oauthServer.allowFormAuthenticationForClients();
		//解决Encoded password does not look like BCrypt报错
		//因为springsecurity在最新版本升级后,默认把之前的明文密码方式给去掉了
		//https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#password-storage-updated
//		oauthServer.passwordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());

	}

	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		//token信息存到redis
		endpoints.tokenServices(tokenServices(endpoints));
		endpoints.authenticationManager(authenticationManager);
		endpoints.tokenStore(tokenStore());

	}

	private TokenStore tokenStore(){
		return  redisTokenStore();
	}

	private MyRedisTokenStore tokenServices(AuthorizationServerEndpointsConfigurer endpoints) {
		MyRedisTokenStore tokenServices = new MyRedisTokenStore();
		tokenServices.setTokenStore(tokenStore());
		tokenServices.setSupportRefreshToken(true);//支持刷新token
		tokenServices.setReuseRefreshToken(true);
		tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
		tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
		addUserDetailsService(tokenServices, userDetailsService);
		return tokenServices;
	}
	private void addUserDetailsService(MyRedisTokenStore tokenServices, UserDetailsService userDetailsService) {
		if (userDetailsService != null) {
			PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
			provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<>(
					userDetailsService));
			tokenServices.setAuthenticationManager(new ProviderManager(Arrays.asList(provider)));
		}
	}

	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

		String finalSecret = "{bcrypt}" + new BCryptPasswordEncoder().encode(clientSecret);
		System.out.println(finalSecret);
//		clients.withClientDetails(clientDetailsService());
//		clients.inMemory()
//				.withClient(clientId)
//				.secret("{bcrypt}"+new BCryptPasswordEncoder().encode(clientSecret))
//				//.redirectUris(redirectUris)
//				.authorizedGrantTypes(authorizedGrantTypes)
//				.scopes(scopes)
//				.resourceIds(resourceIds)
//				.accessTokenValiditySeconds(accessTokenValiditySeconds)
//				.refreshTokenValiditySeconds(refreshTokenValiditySeconds);

		clients.inMemory()
				.withClient(clientId)
				//密码模式及refresh_token模式
				.authorizedGrantTypes("password","refresh_token")
				.scopes("all")
				.secret(finalSecret);
	}


}
